﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using RSCore.Helper.Collection;
using RSEngine.Math;

namespace RSEngine.Core
{

    /// <summary>
    /// A mesh edge.
    /// </summary>
    /// <remarks>
    /// for most algorithms an edge must be adjacent
    /// to only two faces.
    /// </remarks>
    sealed public class Edge
    {

        #region Variables

        public Vertex[] Vertices = new Vertex[2];
        public UnicityList<Face> Faces = new UnicityList<Face>(2);
        public int label = 0;

        #endregion

        #region Constructor

        public Edge()
        {
        }

        #endregion

        #region Properties

        /// <summary>
        /// The lenght of the edge.
        /// </summary>
        public double Length
        {
            get
            {
                return (Vertices[0].Coordinate - Vertices[1].Coordinate).Length;
            }
        }

        /// <summary>
        /// An edge is free when there is no corresponding face.
        /// </summary>
        public bool IsFree
        {
            get
            {
                if (Faces.Count == 0)
                    return true;
                return false;
            }
        }

        /// <summary>
        /// Returns true if the edge is a mesh boundary.
        /// </summary>
        public bool IsBoundary
        {
            get
            {
                if (Faces.Count < 2)
                    return true;

                return false;
            }
        }

        #endregion

        #region Disconnect

        /// <summary>
        /// Disconnect the edge.
        /// </summary>
        public void Disconnect()
        {
            // Disconnect the vertices
            if (Vertices[0] != null)
                Vertices[0].Edges.Remove(this);
            if (Vertices[1] != null)
                Vertices[1].Edges.Remove(this);

            // Disconnect the faces
            for (int index = 0; index < Faces.Count; index++)
                Faces[index].Edges.Remove(this);

            Vertices[0] = Vertices[1] = null;
            Faces.Clear();
        }

        #endregion

        #region Replace

        /// <summary>
        /// Replace a vertex with another one.
        /// </summary>
        public void Replace(Vertex oldVertex, Vertex newVertex)
        {
            for (int i = 0; i < 2; i++)
                if (Vertices[i] == oldVertex)
                {
                    oldVertex.Edges.Remove(this);
                    Vertices[i] = newVertex;
                    newVertex.Edges.Add(this);
                }
        }

        #endregion

        #region Clone

        public Edge Clone()
        {
            Edge e = new Edge();
            e.Vertices = (Vertex[])Vertices.Clone();
            e.Faces = Faces.Clone();
            e.label = label;
            return e;
        }

        #endregion

        #region Misc

        public override bool Equals(object obj)
        {
            Edge e1 = this;
            Edge e2 = (Edge)obj;
            if (e1.Vertices[0].Equals(e2.Vertices[0]))
            {
                if (e1.Vertices[1].Equals(e2.Vertices[1]))
                    return true;
                else
                    return false;
            }
            else if (e1.Vertices[0].Equals(e2.Vertices[1]))
            {
                if (e1.Vertices[1].Equals(e2.Vertices[0]))
                    return true;
                else
                    return false;
            }
            else return false;
        }

        #endregion

    }

}
